﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using System.Net.Http;
using System.Xml;
using System.Threading;
using HtmlAgilityPack;
using Newtonsoft.Json;
using System.Web.UI.WebControls;

namespace moni
{
    public partial class FormMain : Form
    {
        private string gdzh_sz = "00122490552";
        private string gdzh_sh = "A498210895";
        public static string cookies = "";
        public ChromiumWebBrowser chromeBrowser;
        public int port = 8091;
       static string currentPath= System.Environment.CurrentDirectory;
        static string cachePath = currentPath + @"\Cache";
        string userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36";
        public FormMain()
        {
            string portObj = ConfigHelper.GetAppConfig("port", null);
            if (null== portObj) {
                ConfigHelper.UpdateAppConfig("port", port.ToString(), null);
            }
            else 
            {
                port = int.Parse(portObj.ToString());
            }
            InitializeComponent();
            //打开网页
            InitializeChromium();
            InitWebServer();
            this.timer1.Interval = 30000;
            this.timer1.Start();
            this.Text = "API模拟接口---端口"+port;
        }
        private delegate void ShowLogDataDelegate(string log);
        private void ShowLogData(string log)
        {
            if (richTextBoxLog.Text.Length <= 10000)
            {
                richTextBoxLog.Text = log + "\r\n" + richTextBoxLog.Text;
            }
            else
            {
                richTextBoxLog.Text = log;
            }
        }
        HttpListener httpListenner;
        Thread listernnerThread;
        private void InitWebServer()
        {
            httpListenner = new HttpListener();
            httpListenner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
            httpListenner.Prefixes.Add("http://localhost:"+ port + "/");
            httpListenner.Start();
            listernnerThread = new Thread(new ThreadStart(delegate
            {
                try
                {
                    loop(httpListenner);
                }
                catch (Exception)
                {
                    ShowLogData("InitWebServer 意外停止，重启中");
                    try
                    {
                        httpListenner.Stop();
                    }
                    catch (Exception)
                    {
                        ShowLogData("InitWebServer停止失败");
                    }
                    httpListenner = new HttpListener();
                    httpListenner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                    httpListenner.Prefixes.Add("http://localhost:" + port + "/");
                    httpListenner.Start();
                }
            }));
            listernnerThread.Start();
            ShowLogData("InitWebServer 启动成功");
        }
        private void loop(HttpListener httpListenner)
        {
            ShowLogDataDelegate showLogDataDelegate = new ShowLogDataDelegate(ShowLogData);
            while (true)
            {
                HttpListenerResponse response = null;
                try
                {
                    this.Invoke(showLogDataDelegate, "请求发生 ------");
                    HttpListenerContext context = httpListenner.GetContext();
                    HttpListenerRequest request = context.Request;
                    response = context.Response;
                    Servlet servlet = new MyServlet(this);
                    servlet.onCreate();
                    if (request.HttpMethod == "POST")
                    {
                        servlet.onPost(request, response);
                    }
                    else if (request.HttpMethod == "GET")
                    {
                        servlet.onGet(request, response);
                    }
                    response.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("server端发生异常");
                    this.Invoke(showLogDataDelegate, "server端，请求发生异常："+ex.StackTrace);
                }
                finally {
                    if (null!= response)
                    {
                        response.Close();
                    }
                }
            }
        }

        //初始化浏览器并启动
        public void InitializeChromium()
        {
            CefSettings settings = new CefSettings
            {
                IgnoreCertificateErrors = true, //忽略证书错误问题
                UserAgent = userAgent, //浏览器的请求头
                Locale = "zh-CN", // 将传递给Blink的语言环境字符串。如果为空，则将使用默认语言环境“ en-US”
                BrowserSubprocessPath = currentPath + @"\CefSharp.BrowserSubprocess.exe",
                AcceptLanguageList = "zh-CN,zh;q=0.8",//浏览器引擎的语言
                PersistSessionCookies = false,//保存回话
                PersistUserPreferences=false,
                CachePath = cachePath, //缓存文件保存目录：默认情况下，CEF使用内存缓存来保存缓存的数据，例如 要保留cookie，您需要指定一个缓存路径
            };
            settings.CefCommandLineArgs.Add("disable-gpu", "1");
            Cef.EnableHighDPISupport();
            Cef.Initialize(settings);
            chromeBrowser = new ChromiumWebBrowser("http://moni.10jqka.com.cn/");
            chromeBrowser.FrameLoadEnd += webBrowser_FrameLoadEnd;

            //RequestContextSettings requestContextSettings = new RequestContextSettings();
            //requestContextSettings.PersistSessionCookies = false;
            //requestContextSettings.PersistUserPreferences = false;
            //chromeBrowser.RequestContext = new RequestContext(requestContextSettings);

            // Add it to the form and fill it to the form window.
            this.tabControl1.TabPages[0].Controls.Add(chromeBrowser);
            //panel1.Controls.Add(chromeBrowser);
            chromeBrowser.Dock = DockStyle.Fill;
        }
        public static CookieCollection GetCookieCollection()
        {
            CookieCollection cookieCollection = new CookieCollection();
            string[] arr = cookies.Split('$');
            foreach (string s in arr)
            {
                if (string.IsNullOrEmpty(s))
                    continue;
                string[] car = s.Split('^');
                System.Net.Cookie cookie = new System.Net.Cookie();
                cookie.Domain = car[0];
                cookie.Name = car[1];
                cookie.Value = car[2];
                cookieCollection.Add(cookie);
            }
            return cookieCollection;
        }
        public static string GetCookieCollectionString()
        {
            StringBuilder ret = new StringBuilder();
            string[] arr = cookies.Split('$');
            foreach (string s in arr)
            {
                if (string.IsNullOrEmpty(s))
                    continue;
                string[] car = s.Split('^');
                System.Net.Cookie cookie = new System.Net.Cookie();
                cookie.Domain = car[0];
                cookie.Name = car[1];
                cookie.Value = car[2];
                if(cookie.Domain== "mncg.10jqka.com.cn"|| cookie.Domain== "10jqka.com.cn")
                {
                    ret.Append(System.Web.HttpUtility.UrlEncode(cookie.Name, System.Text.Encoding.UTF8) + "=" + cookie.Value + "; ");
                }
            }
            return ret.ToString();
        }
        public string createOrder(int type,string stockcode,string price,string amount,int orderType)
        {
            string url = "http://mncg.10jqka.com.cn/cgiwt/delegate/tradestock/";
            HttpRequestMessage http_req_msg = new HttpRequestMessage();
            http_req_msg.Method = HttpMethod.Post;
            http_req_msg = addHeader(http_req_msg);
            http_req_msg.RequestUri = new Uri(url);
            HttpClient httpclient;
            HttpClientHandler httphandler;
            httphandler = new HttpClientHandler();
            httphandler.AllowAutoRedirect = false;
            httphandler.UseCookies = false;
            httpclient = new HttpClient(httphandler);
            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
            if (orderType == 1)
            {
                KeyValuePair<string, string> one = new KeyValuePair<string, string>("type", "cmd_wt_mairu");
                list.Add(one);
            }
            else {
                KeyValuePair<string, string> one = new KeyValuePair<string, string>("type", "cmd_wt_maichu");
                list.Add(one);
            }
            if (type == 1)
            {
                KeyValuePair<string, string> one1 = new KeyValuePair<string, string>("mkcode", "1");
                list.Add(one1);
                KeyValuePair<string, string> one2 = new KeyValuePair<string, string>("gdzh", gdzh_sz);
                list.Add(one2);
            }
            else {
                KeyValuePair<string, string> one1 = new KeyValuePair<string, string>("mkcode", "2");
                list.Add(one1);
                KeyValuePair<string, string> one2 = new KeyValuePair<string, string>("gdzh", gdzh_sh);
                list.Add(one2);
            }
            KeyValuePair<string, string> one3 = new KeyValuePair<string, string>("stockcode", stockcode);
            list.Add(one3);
            KeyValuePair<string, string> one4 = new KeyValuePair<string, string>("price", price);
            list.Add(one4);
            KeyValuePair<string, string> one5= new KeyValuePair<string, string>("amount", amount);
            list.Add(one5);
            FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(list);
            http_req_msg.Content = formUrlEncodedContent;
            var task = httpclient.SendAsync(http_req_msg);
            //task.Result.EnsureSuccessStatusCode();
            HttpResponseMessage response = task.Result;
            var result = response.Content.ReadAsStringAsync();
            string responseBodyAsText = result.Result;
            return responseBodyAsText;
        }
        public List<DelegatedData> getDelegated() {
            List<DelegatedData> datas = new List<DelegatedData>();
            string url = "http://mncg.10jqka.com.cn/cgiwt/stock/delegateddiv/?ajaxdatatype=html";
            HttpRequestMessage http_req_msg = new HttpRequestMessage();
            http_req_msg.Method = HttpMethod.Get;
            http_req_msg = addHeader(http_req_msg);
            http_req_msg.RequestUri = new Uri(url);
            HttpClient httpclient;
            HttpClientHandler httphandler;
            httphandler = new HttpClientHandler();
            httphandler.AllowAutoRedirect = false;
            httphandler.UseCookies = false;
            httpclient = new HttpClient(httphandler);
            var task = httpclient.SendAsync(http_req_msg);
            //task.Result.EnsureSuccessStatusCode();
            HttpResponseMessage response = task.Result;
            var result = response.Content.ReadAsStringAsync();
            string responseBodyAsText = result.Result;
            if (responseBodyAsText.IndexOf("<table name=\"qryChedan\" class=\"tablesorter\" style=\"\">") > 0)
            {
                //获取内容，正则处理
                int start = responseBodyAsText.IndexOf("<table name=\"qryChedan\" class=\"tablesorter\" style=\"\">");
                int end = responseBodyAsText.IndexOf("</table>", start);
                if (end > 0)
                {
                    responseBodyAsText = responseBodyAsText.Substring(start, end - start+ "</table>".Length);
                }
                HtmlAgilityPack.HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
                htmlDocument.LoadHtml(responseBodyAsText);//加载HTML字符串，如果是文件可以用htmlDocument.Load方法加载

                HtmlNodeCollection collection = htmlDocument.DocumentNode.SelectSingleNode("table").ChildNodes;//跟Xpath一样，轻松的定位到相应节点下
                foreach (HtmlNode node in collection)
                {
                    HtmlNodeCollection collectionTd = node.ChildNodes;
                    if (collectionTd.Count > 12)
                    {
                        datas.Add(new DelegatedData()
                        {
                            证券代码 = collectionTd[0].InnerText.ToString(),
                            证券名称= collectionTd[1].InnerText.ToString(),
                            备注 = collectionTd[2].InnerText.ToString(),
                            委托数量 = collectionTd[3].InnerText.ToString(),
                            成交数量 = collectionTd[4].InnerText.ToString(),
                            委托价格 = collectionTd[5].InnerText.ToString(),
                            成交均价 = collectionTd[6].InnerText.ToString(),
                            操作 = collectionTd[7].InnerText.ToString(),
                            委托时间 = collectionTd[8].InnerText.ToString(),
                            委托日期 = collectionTd[9].InnerText.ToString(),
                            合同编号 = collectionTd[10].InnerText.ToString(),
                            交易市场 = collectionTd[11].InnerText.ToString(),
                            股东账户 = collectionTd[12].InnerText.ToString()
                        });
                    }
                }

            }
            return datas;
        }
        public HttpRequestMessage addHeader(HttpRequestMessage http_req_msg) {
            http_req_msg.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36");
            http_req_msg.Headers.Add("Cookie", GetCookieCollectionString());
            http_req_msg.Headers.Referrer = new Uri("http://mncg.10jqka.com.cn/cgiwt/index/index");
            http_req_msg.Headers.Add("X-Requested-With", "XMLHttpRequest");
            return http_req_msg;
        }
        public string getAccountList()
        {
            string url = "http://moni.10jqka.com.cn/mncg/index/getcjdbs/";
            HttpRequestMessage http_req_msg = new HttpRequestMessage();
            http_req_msg.Method = HttpMethod.Post;
            http_req_msg = addHeader(http_req_msg);
            try
            {
                List<KeyValuePair<string, string>> data = new List<KeyValuePair<string, string>>();
                KeyValuePair<string, string> key = new KeyValuePair<string, string>("perPage", "10");
                data.Add(key);
                HttpContent content = new FormUrlEncodedContent(data);
                http_req_msg.Content = content;
                http_req_msg.RequestUri = new Uri(url);
                HttpClient httpclient;
                HttpClientHandler httphandler;
                httphandler = new HttpClientHandler();
                httphandler.AllowAutoRedirect = false;
                httphandler.UseCookies = false;
                httpclient = new HttpClient(httphandler);
                var task = httpclient.SendAsync(http_req_msg);
                HttpResponseMessage response = task.Result;
                var result = response.Content.ReadAsStringAsync();
                string responseBodyAsText = result.Result;
                JsonSerializer serializer = new JsonSerializer();
                Object dataJson = JsonConvert.DeserializeObject<Object>(responseBodyAsText);
                Newtonsoft.Json.Linq.JObject obj = dataJson as Newtonsoft.Json.Linq.JObject;
                Newtonsoft.Json.Linq.JArray resultDataJson = obj["result"]["data"] as Newtonsoft.Json.Linq.JArray;
                List<ListItem> items = new List<ListItem>();
                for (int i=0;i< resultDataJson.Count;i++) {
                    Newtonsoft.Json.Linq.JObject one =(Newtonsoft.Json.Linq.JObject) resultDataJson[i];
                    items.Add(new ListItem( one["bsName"].ToString(), one["jyUrlOl"].ToString()));
                }
                comboBoxAccountList.DataSource = items;
                return responseBodyAsText;
            }
            catch (HttpRequestException ex)
            {
                return "500";
            }
        }
        public string getCurrentBalance() {
            string url = "http://mncg.10jqka.com.cn/cgiwt/stock/buydiv/?ajaxdatatype=html";
            HttpRequestMessage http_req_msg = new HttpRequestMessage();
            http_req_msg.Method = HttpMethod.Get;
            http_req_msg = addHeader(http_req_msg);
            try
            {
                http_req_msg.RequestUri = new Uri(url);
                HttpClient httpclient;
                HttpClientHandler httphandler;
                httphandler = new HttpClientHandler();
                httphandler.AllowAutoRedirect = false;
                httphandler.UseCookies = false;
                httpclient = new HttpClient(httphandler);
                var task = httpclient.SendAsync(http_req_msg);
                //task.Result.EnsureSuccessStatusCode();
                HttpResponseMessage response = task.Result;
                var result = response.Content.ReadAsStringAsync();
                string responseBodyAsText = result.Result;
                if (responseBodyAsText.IndexOf("var zijinData = ") > 0)
                {
                    //获取内容，正则处理
                    int start = responseBodyAsText.IndexOf("var zijinData = ");
                    int end = responseBodyAsText.IndexOf(";updateUserZjInfo(zijinData);", start);
                    if (end > 0)
                    {
                        responseBodyAsText = responseBodyAsText.Substring(start, end - start);
                    }
                    responseBodyAsText = responseBodyAsText.Remove(0, "var zijinData = ".Length);
                }
                return responseBodyAsText;
            }
            catch (HttpRequestException ex) {
                return "500";
            }
        }
        public List<Data> getCurrentPosition() {
            List<Data> datas = new List<Data>();//定义1个列表用于保存结果
            string url = "http://mncg.10jqka.com.cn/cgiwt/stock/buydiv/?ajaxdatatype=html";
            HttpRequestMessage http_req_msg = new HttpRequestMessage();
            http_req_msg.Method = HttpMethod.Get;
            http_req_msg = addHeader(http_req_msg);
            http_req_msg.RequestUri = new Uri(url);
            HttpClient httpclient;
            HttpClientHandler httphandler;
            httphandler = new HttpClientHandler();
            httphandler.AllowAutoRedirect = false;
            httphandler.UseCookies = false;
            httpclient = new HttpClient(httphandler);
            var task = httpclient.SendAsync(http_req_msg);
            //task.Result.EnsureSuccessStatusCode();
            HttpResponseMessage response = task.Result;
            var result = response.Content.ReadAsStringAsync();
            string responseBodyAsText = result.Result;
            if (responseBodyAsText.IndexOf("<select name=\"gddm\" id=\"gddm\">") >0) {
                int start = responseBodyAsText.IndexOf("<select name=\"gddm\" id=\"gddm\">");
                int end = responseBodyAsText.IndexOf("</select>", start);
                if (end > 0)
                {
                    string responseBodyAsTextInner = responseBodyAsText.Substring(start, end - start + "</select>".Length);
                    HtmlAgilityPack.HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
                    htmlDocument.LoadHtml(responseBodyAsTextInner);//加载HTML字符串，如果是文件可以用htmlDocument.Load方法加载
                    HtmlNodeCollection collection = htmlDocument.DocumentNode.SelectSingleNode("select").ChildNodes;//跟Xpath一样，轻松的定位到相应节点下
                    foreach (HtmlNode node in collection)
                    {
                        string txt=node.InnerText.ToString();
                        if (txt.IndexOf("沪A") >=0) {
                            gdzh_sh = txt.Replace("沪A", "").Replace(" ", "");
                        }
                        else if (txt.IndexOf("深A") >= 0)
                        {
                            gdzh_sz = txt.Replace("深A", "").Replace(" ", "");
                        }
                    }
                 }
            }
            if (responseBodyAsText.IndexOf("<table name=\"qryChicang\" class=\"tablesorter\" style=\"\">") > 0)
            {
                //获取内容，正则处理
                int start = responseBodyAsText.IndexOf("<table name=\"qryChicang\" class=\"tablesorter\" style=\"\">");
                int end=responseBodyAsText.IndexOf("</table>", start);
                if (end > 0)
                {
                    responseBodyAsText = responseBodyAsText.Substring(start, end - start+ "</table>".Length);
                }
                //使用脚本解析

                HtmlAgilityPack.HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
                htmlDocument.LoadHtml(responseBodyAsText);//加载HTML字符串，如果是文件可以用htmlDocument.Load方法加载

                HtmlNodeCollection collection = htmlDocument.DocumentNode.SelectSingleNode("table").ChildNodes;//跟Xpath一样，轻松的定位到相应节点下
                foreach (HtmlNode node in collection)
                {
                    HtmlNodeCollection collectionTd = node.ChildNodes;
                    if (collectionTd.Count>13) {
                        datas.Add(new Data() { 证券代码 = collectionTd[0].InnerText.ToString(),
                            证券名称 = collectionTd[1].InnerText.ToString(),
                            证券余额 = collectionTd[2].InnerText.ToString(),
                            可用余额 = collectionTd[3].InnerText.ToString(),
                            冻结数量 = collectionTd[4].InnerText.ToString(),
                            股票实际 = collectionTd[5].InnerText.ToString(),
                            成本价 = collectionTd[6].InnerText.ToString(),
                            市价 = collectionTd[7].InnerText.ToString(),
                            市值 = collectionTd[8].InnerText.ToString(),
                            浮动盈亏 = collectionTd[9].InnerText.ToString(),
                            盈亏比例 = collectionTd[10].InnerText.ToString(),
                            币种 = collectionTd[11].InnerText.ToString(),
                            交易市场 = collectionTd[12].InnerText.ToString(),
                            股东账户 = collectionTd[13].InnerText.ToString()
                        });
                    }
                }
            }
            return datas;
        }
        
        private async void buttonStart_Click(object sender, EventArgs e)
        {
            //createOrder(1, "000001","17.75","100",1);
            getAccountList();
            getCurrentPosition();
        }
       
        /// 回调事件
        private void visitor_SendCookie(CefSharp.Cookie obj)
        {
            cookies += obj.Domain.TrimStart('.') + "^" + obj.Name + "^" + obj.Value + "$";
            //Console.WriteLine(cookies);
        }
        private void loadCookies() {
            CookieVisitor visitor = new CookieVisitor();
            visitor.SendCookie += visitor_SendCookie;
            ICookieManager cookieManager = chromeBrowser.GetCookieManager();
            cookieManager.VisitAllCookies(visitor);
        }
        async void webBrowser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
        {
            string _url = e.Url;
            //判断是否是需要获取cookie的页面
            if (_url.Contains("10jqka.com.cn"))
            {
                //注册获取cookie回调事件
                loadCookies();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            this.chromeBrowser.Load("http://mncg.10jqka.com.cn/cgiwt/index/index");
            cookies = "";
        }

        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
           
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            chromeBrowser.GetBrowser().CloseBrowser(false);
            chromeBrowser.Dispose();
            CefSharp.Cef.Shutdown();
            listernnerThread.Abort();
            httpListenner.Close();

        }

        private void buttonGoExchangePage_Click(object sender, EventArgs e)
        {
            //进入模拟交易界面
            ListItem selectedItem = (ListItem)comboBoxAccountList.SelectedItem;
            string value = selectedItem.Value;    //值
            string text = selectedItem.Text;    //显示的文字
            if (null!=value) {
                this.chromeBrowser.Load(value);
                cookies = "";
            }
        }
    }
}
